/*
 * GlobalState.hpp
 *
 *  Created on: Sep 4, 2013
 *      Author: jason
 */

#ifndef GLOBALSTATE_HPP_
#define GLOBALSTATE_HPP_
#include "Objects/Characters.hpp"
//#include "Items/Items.hpp"
#include "luaManager.hpp"
#include <unordered_map>
#include <string>
#include <vector>

// This class will store the current progress of the related game events.
// Typically game progression is measured in the progress from one related
// event to another. This class allows easy access to related event groupings.
// Groupings will consist of story progress, side-quests, whatever else
class GlobalEventGroup {
public:
	GlobalEventGroup (std::string name) : groupID(name) {}
	~GlobalEventGroup() {}
	bool doesEventExist(std::string event) { if (eventMap.find(event) != eventMap.end())
		return true;
	else return false;
	}
	int getEventProgress(std::string name);
	void setEventProgress(std::string name, int p = 0);
	int getNumberOfEvents() {return eventMap.size();}
	std::unordered_map<std::string, int> &getEvents() {return eventMap;}
private:
	std::string groupID;
	std::unordered_map<std::string, int> eventMap;
};

// This class controls the battle party.
// The main point of it is to be a container to references to all characters which
// can be brought onto the field when the battle starts.
// When battles start, the battle will iterate through this class and
// organize everyone onto the field based on their index.
// For most battles, only the members whose indices are below maxPartySize (12)
// will be allowed onto the field.
// There should be the option of having a battle in which both the main force and
// secondary force are allowed to battle. For this reason,
// This is the container for the party as a whole rather than just the main force.
class GlobalParty {
public:
	GlobalParty() {}
	~GlobalParty() {}
	int size() {return vMembers.size();}
	void addCharacter(OForce_Object::Character *character);
	void removeCharacter(OForce_Object::Character *character);
	bool isMember(OForce_Object::Character *character);
	// When an item is found outside of a battle, it is necessary to cycle
	// through the characters until a character is found who has room in his inventory
	bool getItem(OForce::GenericItem *); // TODO IMPLEMENT ME
	std::vector<OForce_Object::Character *> vMembers;
private:

};

// This class is meant to keep track of the current state of the game.
// This includes things like party members, stats, items, events etc.
// Saving and loading will dump/fill this for example. Also, this will
// need to be updated in the various game modes.
// There can be only one *explosions and lightning*
// hence the singleton form.
class GlobalState {
public:
	~GlobalState();
	static GlobalState *Instance();
	static void KillInstance();
	// Character Functions
	void addCharacter(OForce_Object::Character *character);
	void addToParty(OForce_Object::Character *character);
	void removeFromParty(OForce_Object::Character *character);
	OForce_Object::Character* getCharacter(int id);
	bool isPartyMember(int id) { bool out =
		(characterMap.find(id) != characterMap.end()) ?  true: false;
	return out;}
	// Economy
	void addGold(int gold) {mGold += gold;}
	void removeGold(int gold) {mGold -= gold;}
	void setGold(int gold) {mGold = gold;}
	int getGold() {return mGold;}
	// Items
	// TODO IMPLEMENT ME
	bool addToInventory(OForce_Object::Character *character, int itemID);
	bool addToPartyInventory(int itemID);
	void removeFromInventory(OForce_Object::Character *character, int itemID);
	// Main character / save file name
	std::string getName() {return playerName;}
	// Lua
	LuaScript &getItemScript() {return itemScript;}
	LuaScript &getWeaponScript() {return weaponScript;}
	LuaScript &getAccessoryScript() {return accessoryScript;}
	LuaScript &getCharacterScript() {return characterScript;}
	// Event functions
	void setPreviousLocation(std::string loc) {prevLocation = loc;}
	bool doesEventGroupExist(std::string name);
	bool doesEventExist(std::string groupName, std::string eventName);
	void addEventGroup(std::string name);
//	void addEvent(std::string groupName, std::string eventName);
	GlobalEventGroup *getEventGroup(std::string groupName);
	int getEventValue(std::string eventGroup, std::string eventName) const;
	void setEventValue(std::string eventGroup, std::string eventName, int value);
	int getNumEventGroups() {return eventGroupMap.size();}
	int getNumEvents(std::string groupName);
	// Game State functions
	void saveGame();
	void loadGame();
	void resetGame();
private:
	static GlobalState* m_pInstance;
	GlobalState();
	std::string playerName;
	int playerGender;  // 1 = female, 2 = male
	int mGold;
	// Lua Scripts
//	LuaScript globalScript;   // Script for global events/functions
	LuaScript itemScript;     // self-explanatory
	LuaScript weaponScript;
	LuaScript accessoryScript;
	LuaScript characterScript;
	// Character organizer
	std::unordered_map<int, OForce_Object::Character *> characterMap;
	// Current battle party:
	GlobalParty battleParty;
	// Event and state variables
	std::string prevLocation;
	std::unordered_map<std::string, GlobalEventGroup *> eventGroupMap;
};


#endif /* GLOBALSTATE_HPP_ */
